table of contents
USBGUARD-RULES.CO(5) | USBGUARD-RULES.CO(5) |
NAME¶
usbguard-rules.conf - USBGuard rule set file.
DESCRIPTION¶
The usbguard-rules.conf file is loaded by the USBGuard daemon after it parses the main configuration file, usbguard-daemon.conf(5). The daemon expects the file to contain rules written in a language which is described in the Rule Language section below.
RULE LANGUAGE¶
The USBGuard daemon decides which USB device to authorize based on a policy defined by a set of rules. When a USB device is inserted into the system, the daemon scans the existing rules sequentially. If a matching rule is found, it either authorizes (allows), deauthorizes (blocks) or removes (rejects) the device, based on the rule target. If no matching rule is found, the decision is based on an implicit default target. This implicit default is to block the device until a decision is made by the user. The rule language grammar, expressed in a BNF-like syntax, is the following:
rule ::= target attributes.
target ::= "allow" | "block" | "reject".
attributes ::= attributes | attribute.
attributes ::= .
Rule attributes specify which devices to match or what condition have to be met for the rule to be applicable. See the Device Specification section for the list of available attributes and Conditions for the list of supported rule rule conditions.
Targets¶
The target of a rule specifies whether the device will be authorized for use or not. Three types of target are recognized:
Device Specification¶
Except the target, all the other fields of a rule are optional. A rule where only the target is specified will match any device. That allows the policy administator to write an explicit default target. If no rule from the policy is applicable to the device, an implicit target configured in usbguard-daemon.conf(5) will be used. However, if one wants to narrow the applicability of a rule to a set of devices or one device only, it’s possible to do so with device attributes and rule conditions.
Device Attributes
Device attributes are specific values read from the USB device after it’s inserted to the system. Which attributes are available is defined below. Some of the attributes are derived and some are based on attributes read directly from the device. All attributes support two forms:
name value
name [operator] { value1 value2 ... }
where the optional operator is one of:
all-of
one-of
none-of
equals
equals-ordered
If the operator is not specified it is set to equals.
List of attributes:
id usb-device-id
id [operator] { usb-device-id ... }
hash "value"
hash [operator] { "value" ... }
parent-hash "value"
parent-hash [operator] { "value" ... }
name "device-name"
name [operator] { "device-name" ... }
serial "serial-number"
serial [operator] { "serial-number" ... }
via-port "port-id"
via-port [operator] { "port-id" ... }
with-interface interface-type
with-interface [operator] { interface-type ... }
The usb-device-id is a colon delimited pair in the form vendor_id:product_id. All USB devices have this ID assigned by the manufacturer and it should uniquely identify a USB product type. Both vendor_id and product_id are 16-bit numbers represented in hexadecimal base. It’s possible to use an asterisk character to match either any device ID *:* or any product ID from a specific vendor, e.g. 1234:*.
The port-id value is a platform specific USB port identification. On Linux it’s in the form of "usbN" in case of a USB controller (more accurately a "root hub") or "bus-port[.port[.port ...]]" (e.g. 1-2, 1-2.1, ...) in case of a USB device.
The interface-type represents a USB interface and should be formatted as three 8-bit numbers in hexadecimal base delimited by a colon character, i.e. cc:ss:pp. The numbers represent the interface class (cc), subclass (ss) and protocol (pp) as assigned by the USB-IF. See the list of assigned classes, subclasses and protocols for details. Instead of the subclass and protocol number, you may write an asterisk character (*) to match all subclasses or protocols. Matching a specific class and a specific protocol is not allowed, i.e. if you use an asterisk as the subclass number, you have to use an asterisk for the protocol too.
Conditions¶
Whether a rule that matches a device will be applied or not can be further restricted using rule conditions. If the condition expression is met at the rule evaluation time, then the rule target is applied for the device. A condition expression is met if it evaluates to true. Otherwise, the rule evaluation continues with the next rule. A rule conditions has the following syntax:
if [!]condition
if [operator] { [!]conditionA [!]conditionB ... }
Optionally, an exclamation mark (!) can be used to negate the result of a condition.
Interpretation of the set operator:
all-of
one-of
none-of
equals
equals-ordered
List of conditions:
localtime(time_range)
allowed-matches(query)
rule-applied
rule-applied(past_duration)
rule-evaluated
rule-evaluated(past_duration)
random
random(p_true)
true
false
INITIAL POLICY¶
Using the usbguard CLI tool and its generate-policy subcommand, you can generate an initial policy for your system instead of writing one from scratch. The tool generates an allow policy for all devices connected to the system at the time of execution. It has several options to tweak the resulting policy, see usbguard(1) for further details.
The policy will be printed out on the standard output. It’s a good idea to review the generated rules before using them on a system. The typical workflow for generating an initial policy could look like this:
EXAMPLE POLICIES¶
The following examples show what to put into the rules.conf file in order to implement the given policy.
This policy will block any device that isn’t just a mass storage device. Devices with a hidden keyboard interface in a USB flash disk will be blocked. Only devices with a single mass storage interface will be allowed to interact with the operating system. The policy consists of a single rule:
allow with-interface equals { 08:*:* }
The blocking is implicit in this case because we didn’t write a block rule. Implicit blocking is useful to desktop users. A desktop applet listening to USBGuard events can ask the user for a decision if an implicit target was applied.
allow 1050:0011 name "Yubico Yubikey II" serial "0001234567" via-port "1-2" hash "044b5e168d40ee0245478416caf3d998"
reject via-port "1-2"
We could use just the hash to match the device. However, using the name and serial attributes provide an useful hint for later inspection of the policy. On the other hand, the hash is the most specific value we can use to identify a device. It’s the best attribute to use if you want a rule to match just one device.
A USB flash disk which implements a keyboard or a network interface is very suspicious. The following set of rules forms a policy that allows USB flash disks and explicitly rejects devices with an additional and suspicious (as defined before) interface.
allow with-interface equals { 08:*:* }
reject with-interface all-of { 08:*:* 03:00:* }
reject with-interface all-of { 08:*:* 03:01:* }
reject with-interface all-of { 08:*:* e0:*:* }
reject with-interface all-of { 08:*:* 02:*:* }
The policy rejects all USB flash disk devices with an interface from the HID/Keyboard, Communications and Wireless classes. Note that blacklisting is the wrong approach and you shouldn’t just blacklist a set of devices and allow the rest. The policy above assumes that blocking is the default. Rejecting a set of devices considered as "bad" is a good approach how to limit the exposure of the OS to such devices as much as possible.
allow with-interface one-of { 03:00:01 03:01:01 } if !allowed-matches(with-interface one-of { 03:00:01 03:01:01 })
allow if random(0.1666)
reject
SEE ALSO¶
04/01/2020 |